#include "mini.kit.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <iostream>

class HttpRange
{
public:
	uint64_t start_byte;
	uint64_t end_byte;
	bool     isRangeRequest;
public:
	HttpRange():
	start_byte(0), end_byte(0), isRangeRequest(false)
	{}
	void Parse(const std::string& sRangeLine)
	{
		//Range: bytes=0-499
		std::string::size_type beginPos = sRangeLine.find("bytes=");
		if ( beginPos == std::string::npos )
			return;
		this->start_byte = strtoull(sRangeLine.substr(beginPos+6).c_str(), NULL, 10);
		std::string::size_type endPos = sRangeLine.find("-");
		if ( endPos == std::string::npos )
			return;
		this->end_byte = strtoul( sRangeLine.substr(endPos+1).c_str(), NULL, 10);
		this->isRangeRequest = true;  
	}
};

class RequestUpload
{
public:
	uint64_t resid;
	uint64_t file_begin;
	uint64_t file_end;
	uint64_t req_begin;
	uint64_t req_end;
	uint64_t cur_begin;
	uint64_t cur_end;
	void*    data_ptr;
public:
	RequestUpload():
	resid(0),
	file_begin(0), file_end(0), 
	req_begin(0), req_end(0),
	cur_begin(0), cur_end(0),
	data_ptr(NULL)
	{}
};

void DownloadRequest(char* buf, uint32_t len);
void PartialUploadRequest(char* buf, uint32_t len);

int main(int argc, char* argv[])
{
	uint32_t ret = 0;

	std::string header_string = "GET /img/for_face/tdefault0_50X50.gif?cmd=image&userid=64410612&ct=aaabbbccc&whatever=ohyeahO HTTP/1.1\r\n\
Accept: */*\r\n\
Referer: http://dynamic.i.xunlei.com/user/growth?cachetime=1292323126671\r\n\
Range: bytes=21010-47021\r\n\
Accept-Language: zh-cn\r\n\
Accept-Encoding: gzip, deflate\r\n\
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)\r\n\
If-Modified-Since: Sat, 29 May 2010 08:52:43 GMT\r\n\
Connection: Keep-Alive\r\n\
Cookie: _xltj=35a1274786857547b20c; __utma=177892794.138263873.1291348606.1291348606.1291348606.1; __utmz=177892794.1291348606.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); luserid=64410612; KANKANWEBUID=d32d8d3bd310f8af8e6f49175f393305; uc_cburl=http%3A%2F%2Fi.xunlei.com%2Fuser%2Findex%2F%3Fcachetime%3D1292323109265; referfrom=; last_u=jiadongzhuang; logintype=0; upgrade=0; nickname=%C4%B7%C3%F7; usernick=%E5%A7%86%E6%98%8E; isvip=5; score=25159; usertype=1; usrname=jiadongzhuang; usernewno=16205798; userid=64410612; jumpkey=27F39D88C7857F587FBEDFA18F9C46F88D9DF66AB2CB1DAD7471812E206BB3D146DA933A426E1DB3FB84561971B99EC59869C8161362DF68F935F92784897EC4D3F9A514A90934DE6125B90D8EC5F99E5367C9D53AA76B4FF31936F8A66E2B54; sessionid=8DC1E7F50CFAF4DFFD91BEE3B500DC8FEA9B1C91DF07D75F7656B8773306E0752A94F64B0F8FE14B718C4394EC98DC27FFCF8A5E312DAEA251E6FDA7C41D372F; uc_vipgrowth=7812; uc_viplevel=5; vip_paytype=5; uc_vip_expiredate=2011-10-02; uc_isvip=1; uc_paytype=5; vipstate=5; title_type=1; intro=ss+god+ss%E5%BA%94%E8%AF%A5%E6%98%AF%E5%90%A7%7E; p_t=64410612\r\n\
Host: iimg.xunlei.com";

	//header_string = "GET /cache?userid=153700960 HTTP/1.1\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; @:Q8]9v4??wgfIW~Ck&fZqc|=j4IAu_bnT6|%)\r\nHost: cache2.vip.xunlei.com:8001\r\nAccept: */*\r\n\r\n";


	DownloadRequest( (char*)header_string.c_str(), header_string.size() );	

	std::string sTestDataChunk="ab27F39D88C785712garwq25123ab";
	RequestUpload reqUp;
	reqUp.file_begin = 0;
	reqUp.file_end = 1234567-1;
	reqUp.req_begin=1234;
	reqUp.req_end=7564;
	reqUp.cur_begin=1235;
	reqUp.cur_end=1245;
	uint32_t len = reqUp.cur_end - reqUp.cur_begin + 1;
	reqUp.data_ptr = new char[len];
	memcpy( reqUp.data_ptr, sTestDataChunk.c_str(), len );
	PartialUploadRequest( (char*)(&reqUp), sizeof(void*) );
	
	
	return 0;
}

void DownloadRequest(char* buf, uint32_t len)
{
	std::string header_string(buf, len);
	std::map<std::string, std::string> fields;
	std::map<std::string, std::string> params;
	//MINIKIT::Http::ParseHeader( header_string, fields, "Cookie,Referer,Connection,Range" );
	MINIKIT::Http::ParseHeader( header_string, fields, "");
        fprintf(stdout, "\nhttp_method: {%s}\n\n", fields["HTTP_METHOD"].c_str() );
        fprintf(stdout, "\nhttp_rawpath: {%s}\n\n", fields["HTTP_RAWPATH"].c_str() );
        fprintf(stdout, "\nhttp_path: {%s}\n\n", fields["HTTP_PATH"].c_str() );
        fprintf(stdout, "\nhttp_querystring: {%s}\n\n", fields["HTTP_QUERYSTRING"].c_str() );
        fprintf(stdout, "\nhttp_version: {%s}\n\n", fields["HTTP_VERSION"].c_str() );
	fprintf(stdout, "\ncookie: {%s}\n\n", fields["COOKIE"].c_str() );
	fprintf(stdout, "\nreferer: {%s}\n\n", fields["REFERER"].c_str() );
	fprintf(stdout, "\nconnection: {%s}\n\n", fields["CONNECTION"].c_str() );
	fprintf(stdout, "\nrange: {%s}\n\n", fields["RANGE"].c_str() );
	//206 //partial-content
        MINIKIT::Http::ParseQueryString( fields["HTTP_QUERYSTRING"], params, "" );
        for(std::map<std::string, std::string>::const_iterator itr=params.begin(); itr!=params.end(); itr++)
        {
                fprintf(stdout, "\tquery-param[%s]=\"%s\"\n", itr->first.c_str(), itr->second.c_str() );
        }

        fprintf(stdout, "------------------\n");
	MINIKIT::Http::ParseCookie( fields["COOKIE"], params, "" ); 
	for(std::map<std::string, std::string>::const_iterator itr=params.begin(); itr!=params.end(); itr++)
	{
		fprintf(stdout, "\tcookies-param[%s]=\"%s\"\n", itr->first.c_str(), itr->second.c_str() );
	}
	

	//LOGIC
	uint64_t filesize = 1234567;
	HttpRange range;
	range.Parse( fields["RANGE"] );
	//range-request
	if( range.isRangeRequest )
	{
		//TODO 
		//put to thread
		fprintf(stdout, "put2thread requesting range [%llu, %llu] \n", range.start_byte, range.end_byte );
	}
	//not-range-request
	else
	{
		//TODO
		//respose immediately
		range.start_byte = 0;
		range.end_byte   = filesize-1;
		
		std::string sContentRange;
		MINIKIT::Text::sprintf( sContentRange, ""
			"HTTP/1.1 200 OK\r\n"
			"Content-Range: bytes %llu-%llu/%llu\r\n"
			"Connection: Close\r\n"
			"Content-Length: %llu\r\n\r\n"
			, range.start_byte, range.end_byte, filesize
			, (range.end_byte-range.start_byte+1)
		);
		fprintf( stdout, "%s", sContentRange.c_str() );
	}
	std::string s;;;;
	MINIKIT::Text::sprintf( s, "function %s at line: %d", __FUNCTION__, __LINE__ );
	fprintf( stdout, "%s\n", s.c_str() );

}

void PartialUploadRequest(char* buf, uint32_t len)
{
	RequestUpload *req = (RequestUpload*)(buf);
	std::string sOut;
	std::string sData = std::string( (char*)req->data_ptr, req->cur_end-req->cur_begin+1);
	if( req->req_begin==req->cur_begin)
	{
		
		MINIKIT::Text::sprintf( sOut, ""
			"HTTP/1.1 206 OK\r\n"
			"Content-Range: bytes %llu-%llu/%llu\r\n"
			"Connection: Close\r\n"
			"Content-Length: %llu\r\n\r\n%s"
			, req->req_begin, req->req_end, (req->file_end-req->file_begin+1)
			, (req->req_end-req->req_begin+1)
			, sData.c_str()
		);
	}
	else if( req->req_begin<req->cur_begin)
	{
		//MINIKIT::Text::sprintf( sOut, "{{yoyo%d,%s,%lluyoyo}}", 123, sData.c_str(), 456789L );
		MINIKIT::Text::sprintf( sOut, "xlstd.listen_host_%d", 123);
	}
	else
	{
		fprintf(stderr, "err:cur_begin.\n");
	}
	std::cout<<"parital-download\r\n["<<sOut<<"].."<<123132<<"\n";
	std::cout<<"parital-download\r\n["<<sOut.c_str()<<"].."<<11111<<"..\n";
	fprintf(stdout, "parital-download\r\n[%s]\n", sOut.c_str());
	
}


